home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xtopo / xtopo.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  27KB  |  849 lines

  1. /*
  2.  *    @(#) xtopo.c 1.5 93/11/12 MRINC
  3.  *
  4.  *    Written using CGI 10 Jun 1987 by Ron Record (rr@sco.com)
  5.  *    Rewritten using X11 21 Oct 1992 by Ron Record (rr@sco.com)
  6.  *
  7.  *  xtopo calculates and displays a fractal artificial landscape.
  8.  *  The landscape is displayed topographically with colors representing height.
  9.  */
  10. /*************************************************************************
  11.  *                                                                       *
  12.  *  Copyright (c) 1987-1993 Ronald Joe Record                            *
  13.  *                                                                       *
  14.  *  All rights reserved. No part of this program or publication may be   *
  15.  *  reproduced, transmitted, transcribed, stored in a retrieval system,  *
  16.  *  or translated into any language or computer language, in any form or *
  17.  *  by any means, electronic, mechanical, magnetic, optical, chemical,   *
  18.  *  biological, or otherwise, without the prior written permission of:   *
  19.  *                                                                       *
  20.  *      Ronald Joe Record (408) 458-3718                                 *
  21.  *      212 Owen St., Santa Cruz, California 95062 USA                   *
  22.  *                                                                       *
  23.  *************************************************************************/
  24.  
  25.  
  26. #include "xtopo.h"
  27.  
  28. int first_row, last_row;
  29. int nrows=1024, nummaps=1, ranbeta=0, delay=0, xpos=-1, ypos=-1;
  30. int demo=0, useroot=0, full=0, oflag=0, spin=0, vflag=0, origin[2];
  31. int maxcolor, colors, width, height, offset, next, sea_pixel;
  32. double beta, min, max, rmax=1.0, rmin=0.0;
  33. double sea_level=0.35;
  34. double **xy;
  35. char *outname;
  36.  
  37. extern double drand48();
  38. extern void BufferPoint(), InitBuffer(), FlushBuffer();
  39.  
  40. void
  41. usage()
  42. {
  43.     printf("Usage: xtopo [-o file][-dsuFRTV][-S level][-H beta]");
  44.     printf("[-m #][-w width][-h height]\n");
  45.     printf("\nWhere :\n\t0 < beta < 1 (default is 0.5)\n");
  46.     printf("\t0 < level < 1 (default is 0.35)\n");
  47.     printf("\t-d indicates demo mode\n");
  48.     printf("\t-s indicates spin color wheel when done computing\n");
  49.     printf("\t-T indicates use Thin array (512x512)\n");
  50.     printf("\t-R indicates use the root window\n");
  51.     printf("\t-V indicates use Very Thin array (256x256)\n");
  52.     printf("\t-m # indicates a minimum color index of # (0-255)\n");
  53.     printf("\t-o file will save the output as 'file' in PPM format\n");
  54.     printf("\t-w # indicates a window width of #\n");
  55.     printf("\t-h # indicates a window height of #\n");
  56.     printf("\t-u produces this message\n");
  57.     printf("During display :\n");
  58.     printf("\t'f' or 'F' will save the picture as a PPM file\n");
  59.     printf("\t'+' will increment and '-' decrement the minimum color index\n");
  60.     printf("\t'>' will increment and '<' decrement the sea level\n");
  61.     printf("\t'0' - '9' will set the sea level to 0.0 - 0.9\n");
  62.     printf("\t'r' or 's' will spin the color wheel forwards or backwards\n");
  63.     printf("\t'W' will increment and 'w' decrement the color map selection\n");
  64.     printf("\t'?' or 'h' will display the usage message\n");
  65.     printf("\t'q' or 'Q' will quit\n");
  66. }
  67.  
  68. void
  69. grafline(line, off, size, row)
  70. double *line[];
  71. int off;
  72. int size;
  73. int row;
  74. {
  75.     static int i, cell;
  76.     double peak, breadth, trans;
  77.  
  78.     breadth = max - min;
  79.     peak = 1.0 - sea_level;
  80.  
  81.     for (i=0; i<size; i++) {
  82.        trans = (line[row][i+off] - min)/breadth;
  83.        if (trans < sea_level)
  84.          cell = sea_pixel;
  85.        else
  86.          cell=(int)(((trans-sea_level)/peak)*((double)colors-1.0))+STARTCOLOR;
  87.        BufferPoint(dpy, canvas, pixmap, Data_GC, &Points, cell, 
  88.                     origin[0] + i, origin[1]);
  89.     }
  90.     origin[1]++;
  91.     if (origin[1] >= XDisplayHeight(dpy, screen))
  92.         origin[1] = 0;
  93. }
  94.  
  95. void
  96. init_contexts()
  97. {
  98.     static int i;
  99.  
  100.     /*
  101.      * create default, writable, graphics contexts for the canvas.
  102.      */
  103.     Data_GC[0] = XCreateGC(dpy, DefaultRootWindow(dpy),
  104.         (unsigned long) NULL, (XGCValues *) NULL);
  105.     /* set the background to black */
  106.     XSetBackground(dpy,Data_GC[0],BlackPixel(dpy, screen));
  107.     /* set the foreground of the 0th context to white */
  108.     XSetForeground(dpy, Data_GC[0], WhitePixel(dpy, screen));
  109.     Data_GC[1] = XCreateGC(dpy, DefaultRootWindow(dpy),
  110.         (unsigned long) NULL, (XGCValues *) NULL);
  111.     /* set the background to white */
  112.     XSetBackground(dpy,Data_GC[1],WhitePixel(dpy, screen));
  113.     /* set the foreground of the 1st context to black */
  114.     XSetForeground(dpy, Data_GC[1], BlackPixel(dpy,  screen));
  115.     for (i=2; i<maxcolor; i++) {
  116.         Data_GC[i] = XCreateGC(dpy, DefaultRootWindow(dpy),
  117.             (unsigned long) NULL, (XGCValues *) NULL);
  118.         /* set the background to black */
  119.         XSetBackground(dpy,Data_GC[i],BlackPixel(dpy, screen));
  120.         /* set the foreground of the ith context to i */
  121.         XSetForeground(dpy, Data_GC[i], i);
  122.     }
  123.     sea_pixel = BlackPixel(dpy, screen);
  124. }
  125.  
  126. void
  127. Clear()
  128. {
  129.     XFillRectangle(dpy, pixmap, Data_GC[0], 0, 0, width, height);
  130.     XCopyArea(dpy, pixmap, canvas, Data_GC[0], 0, 0, width, height, 0, 0);
  131. }
  132.  
  133. void
  134. freemem()
  135. {
  136.     static int i;
  137.  
  138.     for (i=0;i<=nrows;i++)
  139.         free(xy[i]);
  140.     free(xy);
  141. }
  142.  
  143. void
  144. setupmem()
  145. {
  146.     static int i;
  147.  
  148.     if ((xy=(double **)malloc((nrows+1)*sizeof(double *))) == (double **)NULL) {
  149.         printf("Error malloc'ing xy.\n");
  150.         exit (-1);
  151.     }
  152.     for (i=0;i<=nrows;i++) {
  153.         if ((xy[i]=(double *)malloc((nrows+1)*sizeof(double)))==(double *)NULL){
  154.             printf("Error malloc'ing xy[%d].\n", i);
  155.             exit (-1);
  156.         }
  157.     }
  158. }
  159.  
  160. double
  161. gauss()
  162. {
  163.     return(2.0 * drand48()) - 1.0;
  164. }
  165.     
  166. double
  167. pgauss()
  168. {
  169.     double r;
  170.  
  171.     r = gauss();
  172.     if (min > r) min = r;
  173.     if (max < r) max = r;
  174.     return(r);
  175. }
  176.     
  177. void
  178. init_pts(line,size)
  179. double *line[];
  180. int size;
  181. {
  182.     int mid;
  183.  
  184.     mid=size/2;
  185.  
  186.     line[0][size]=pgauss(); line[0][mid]=pgauss(); line[0][0]=pgauss();
  187.     line[size][size]=pgauss(); line[size][mid]=pgauss();
  188.     line[size][0]=pgauss(); line[mid][size]=pgauss(); 
  189.     line[mid][mid]=pgauss(); line[mid][0]=pgauss();
  190. }
  191.  
  192. #define x_str 10
  193.  
  194. void
  195. print_help() 
  196. {
  197.     static char str[80];
  198.     static int y_str, spacing;
  199.     static int ascent, descent, dir;
  200.     static XCharStruct overall;
  201.     static GC gc;
  202.  
  203.     gc = Data_GC[0];
  204.     XClearWindow(dpy, help);
  205.     y_str = 40;
  206.     sprintf(str,"During run-time, interactive control can be exerted via : ");
  207.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  208.     XQueryTextExtents(dpy,(XID)XGContextFromGC(gc),"Hey!",
  209.             4,&dir,&ascent,&descent,&overall);
  210.     spacing = ascent + descent + 5;
  211.     y_str += 2 * spacing;
  212.     sprintf(str,"        < lowers the sea level, > raises it");
  213.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  214.     y_str += spacing;
  215.     sprintf(str,"        0 - 9 sets the sea level to 0.0 - 0.9");
  216.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  217.     y_str += spacing;
  218.     sprintf(str,"        { lowers the value of beta, } raises it");
  219.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  220.     y_str += spacing;
  221.     sprintf(str,"        - lowers the value of mincolindex, + raises it");
  222.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  223.     y_str += spacing;
  224.     sprintf(str,"        d decreases the delay, D increases it");
  225.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  226.     y_str += spacing;
  227.     sprintf(str,"        f or F saves landscape to a PPM file");
  228.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  229.     y_str += spacing;
  230.     sprintf(str,"        h or H or ? displays this message");
  231.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  232.     y_str += spacing;
  233.     sprintf(str,"        n goes on to the next landscape");
  234.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  235.     y_str += spacing;
  236.     sprintf(str,"        N creates a new replacement landscape");
  237.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  238.     y_str += spacing;
  239.     sprintf(str,"        r or s spins the colorwheel");
  240.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  241.     y_str += spacing;
  242.     sprintf(str,"        R or S stops the colorwheel spin");
  243.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  244.     y_str += spacing;
  245.     sprintf(str,"        v or V toggles the sea between black and white");
  246.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  247.     y_str += spacing;
  248.     sprintf(str,"        w decrements, W increments the color wheel index");
  249.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  250.     y_str += spacing;
  251.     sprintf(str,"        <ctrl>-W reads the colormap in $HOME/.xtopomap");
  252.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  253.     y_str += spacing;
  254.     sprintf(str,"        q or Q exits");
  255.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  256.     y_str += 2*spacing;
  257.     sprintf(str,"Press 'h', 'H', or '?' to unmap the help window");
  258.     XDrawImageString(dpy,help,gc,x_str,y_str,str,strlen(str));
  259. }
  260.  
  261. void
  262. redisplay (event)
  263. XExposeEvent    *event;
  264. {
  265.     if (event->window == help)
  266.         print_help();
  267.     else {
  268.         /*
  269.         * Extract the exposed area from the event and copy
  270.         * from the saved pixmap to the window.
  271.         */
  272.         XCopyArea(dpy, pixmap, canvas, Data_GC[0], event->x, event->y, 
  273.             event->width, event->height, event->x, event->y);
  274.     }
  275. }
  276.  
  277. void
  278. resize()
  279. {
  280.     Window r;
  281.     int j; 
  282.     int x, y;
  283.     unsigned int bw, d, new_w, new_h;
  284.     extern void Clear(), midpoint(), event_loop();
  285.  
  286.     freemem();
  287.     XGetGeometry(dpy,canvas,&r,&x,&y,&new_w,&new_h,&bw,&d);
  288.     if (((int)new_w == width) && ((int)new_h == height)) {
  289.         setupmem();
  290.         return;
  291.     }
  292.     width = (int)new_w; height = (int)new_h;
  293.     if (pixmap)
  294.         XFreePixmap(dpy, pixmap);
  295.     pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), 
  296.             width, height, DefaultDepth(dpy, screen));
  297.     while (Max(width, height) > nrows)
  298.         nrows *= 2;
  299.     first_row = (nrows - height) / 2;
  300.     last_row = nrows - first_row;
  301.     setupmem();
  302.     origin[0] = origin[1] = 0;
  303.     InitBuffer(&Points, maxcolor);
  304.     Clear();
  305.     init_pts(xy,nrows);
  306.     midpoint(xy,nrows,beta);
  307.     for (j=first_row; j < last_row; j++) {
  308.         event_loop();
  309.         grafline(xy,offset,width,j);
  310.     }
  311.     FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  312. }
  313.  
  314. void
  315. Cleanup() {
  316.     freemem();
  317.     XCloseDisplay(dpy);
  318. }
  319.  
  320. /* Store artificial landscape in PPM format */
  321. void
  322. save()
  323. {
  324.     FILE *outfile;
  325.     unsigned char c;
  326.     XImage *ximage;
  327.     static int i,j;
  328.     struct Colormap {
  329.         unsigned char red;
  330.         unsigned char green;
  331.         unsigned char blue;
  332.     };
  333.     struct Colormap *colormap=NULL;
  334.  
  335.     if ((colormap=
  336.         (struct Colormap *)malloc(sizeof(struct Colormap)*maxcolor))
  337.             == NULL) {
  338.         fprintf(stderr,"Error malloc'ing colormap array\n");
  339.         Cleanup();
  340.         exit(-1);
  341.     }
  342.     outfile = fopen(outname,"w");
  343.     if(!outfile) {
  344.         perror(outname);
  345.         Cleanup();
  346.         exit(-1);
  347.     }
  348.  
  349.     ximage=XGetImage(dpy, pixmap, 0, 0, width, height, AllPlanes, ZPixmap);
  350.  
  351.     for (i=0;i<maxcolor;i++) {
  352.         colormap[i].red=(unsigned char)(Colors[i].red >> 8);
  353.         colormap[i].green=(unsigned char)(Colors[i].green >> 8);
  354.         colormap[i].blue =(unsigned char)(Colors[i].blue >> 8);
  355.     }
  356.     fprintf(outfile,"P%d %d %d\n",6,width,height);
  357.     fprintf(outfile,"# sea_level=%f nrows=%d beta=%f\n",sea_level,nrows,beta);
  358.     fprintf(outfile,"%d\n",maxcolor-1);
  359.  
  360.     for (j=0;j<height;j++)
  361.         for (i=0;i<width;i++) {
  362.             c = (unsigned char)XGetPixel(ximage,i,j);
  363.             fwrite((char *)&colormap[c],sizeof colormap[0],1,outfile);
  364.         }
  365.     fclose(outfile);
  366.     free(colormap);
  367. }
  368.  
  369. void
  370. redraw() {        /* just redraw the points under sea level */
  371.     static int i, j;
  372.     static double trans;
  373.  
  374.     for (j=first_row; j < last_row; j++) {
  375.         for (i=0; i<width; i++) {
  376.             trans = (xy[j][i+offset] - min)/(max - min);
  377.             if (trans < sea_level)
  378.                 BufferPoint(dpy, canvas, pixmap, Data_GC, &Points, sea_pixel, 
  379.                             i, j - first_row);
  380.         }
  381.     }
  382.     FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  383. }
  384.  
  385. void
  386. Redraw() {
  387.     static int j;
  388.     extern void event_loop();
  389.  
  390.     origin[1] = origin[0] = 0;
  391.     for (j=first_row; j < last_row; j++) {
  392.         event_loop();
  393.         grafline(xy,offset,width,j);
  394.     }
  395.     FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  396. }
  397.  
  398. void
  399. Getkey(event)
  400. XKeyEvent *event;
  401. {
  402.     char key;
  403.     static int spinning=0, spindir=0;
  404.     static XWindowAttributes attr;
  405.     extern void init_color(), write_cmap();
  406.  
  407.     if (XLookupString(event, (char *)&key, sizeof(key), (KeySym *)0,
  408.        (XComposeStatus *) 0) > 0)
  409.             switch (key) {
  410.                 case '\015': /*write out current colormap to $HOME/.<prog>map*/
  411.                     write_cmap(dpy,cmap,Colors,maxcolor,"xtopo","Xtopo");
  412.                     break;
  413.                 case '+': mincolindex += INDEXINC;
  414.                     if (mincolindex > maxcolor)
  415.                         mincolindex = 1;
  416.                     init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  417.                             mincolindex,maxcolor,numwheels,"xtopo","Xtopo",0);
  418.                     break;
  419.                 case '-': mincolindex -= INDEXINC;
  420.                     if (mincolindex < 1)
  421.                         mincolindex = maxcolor - 1;
  422.                     init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  423.                             mincolindex,maxcolor,numwheels,"xtopo","Xtopo",0);
  424.                     break;
  425.                 case '}':    /* increment beta by 0.1 */
  426.                     beta += 0.1;
  427.                     break;
  428.                 case '{':    /* decrement beta by 0.1 */
  429.                     beta -= 0.1;
  430.                     break;
  431.                 case '>':
  432.                     sea_level += 0.1;
  433.                     if (sea_level > 1.0) {
  434.                         sea_level -= 0.1;
  435.                         sea_level = (sea_level + 1.0) / 2.0;
  436.                     }
  437.                     Redraw();
  438.                     break;
  439.                 case '<':
  440.                     sea_level -= 0.1;
  441.                     if (sea_level < 0.0) {
  442.                         sea_level += 0.1;
  443.                         sea_level = sea_level / 2.0;
  444.                     }
  445.                     Redraw();
  446.                     break;
  447.                 case '0':
  448.                 case '1':
  449.                 case '2':
  450.                 case '3':
  451.                 case '4':
  452.                 case '5':
  453.                 case '6':
  454.                 case '7':
  455.                 case '8':
  456.                 case '9':
  457.                     sea_level = (double)atoi((char *)&key) / 10.0;
  458.                     Redraw();
  459.                     break;
  460.                 case 'd': delay -= 25; if (delay < 0) delay = 0; break;
  461.                 case 'D': delay += 25; break;
  462.                 case 'f':    /* save in PPM format file */
  463.                 case 'F': save(); break;
  464.                 case 'n':    /* go on to the next landscape */
  465.                     next = 1;
  466.                     break;
  467.                 case 'N':    /* go on to the next landscape */
  468.                     nummaps++;    /* but don't increment the landscape counter */
  469.                     next = 1;
  470.                     break;
  471.                 case 'S':
  472.                 case 'R': spinning=0;
  473.                     break;
  474.                 case 'r': spinning=1; spindir=1; 
  475.                     Spin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, 1);
  476.                     break;
  477.                 case 's': spinning=1; spindir=0;
  478.                     Spin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, 0);
  479.                     break;
  480.                 case '\027': /* (ctrl-W) read palette from $HOME/.xtopomap */
  481.                   numwheels = 0;
  482.                   init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  483.                             mincolindex,maxcolor,numwheels,"xtopo","Xtopo",0);
  484.                   break;
  485.                 case 'v':
  486.                 case 'V': sea_pixel = (!sea_pixel); redraw(); break;
  487.                 case 'W': 
  488.                     if (numwheels < MAXWHEELS)
  489.                         numwheels++;
  490.                     else
  491.                         numwheels = 0;
  492.                     init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  493.                             mincolindex,maxcolor,numwheels,"xtopo","Xtopo",0);
  494.                     break;
  495.                 case 'w': 
  496.                     if (numwheels > 0)
  497.                         numwheels--;
  498.                     else
  499.                         numwheels = MAXWHEELS;
  500.                     init_color(dpy,canvas,cmap,Colors,STARTCOLOR,
  501.                             mincolindex,maxcolor,numwheels,"xtopo","Xtopo",0);
  502.                     break;
  503.                 case '?':
  504.                 case 'h': XGetWindowAttributes(dpy, help, &attr);
  505.                     if (attr.map_state != IsUnmapped)
  506.                         XUnmapWindow(dpy, help);
  507.                     else {
  508.                         XMapRaised(dpy, help);
  509.                         print_help();
  510.                     }
  511.                     break;
  512.                 case 'Q':
  513.                 case 'q': Cleanup(); exit(0); break;
  514.             }
  515.             if (spinning)
  516.                 Spin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, spindir);
  517. }
  518.  
  519. void
  520. parseargs(argc, argv)
  521. int argc;
  522. char *argv[];
  523. {
  524.     int c;
  525.     extern int optind, getopt();
  526.     extern double atof();
  527.     extern char *optarg;
  528.  
  529.     outname = "xtopo.ppm";
  530.     beta = 0.5;
  531.     width = 512; height = 480;
  532.     while((c = getopt(argc, argv, "drsuFRTVa:b:c:h:m:n:o:w:D:H:S:X:Y:")) != EOF)
  533.     {    switch(c)
  534.         {
  535.         case 'a':
  536.             rmin = atof(optarg);
  537.             break;
  538.         case 'b':
  539.             rmax = atof(optarg);
  540.             break;
  541.         case 'c':
  542.             numwheels = atoi(optarg);
  543.             if (numwheels > MAXWHEELS)
  544.                 numwheels = MAXWHEELS;
  545.             if (numwheels < 0)
  546.                 numwheels = 0;
  547.             break;
  548.         case 'd':
  549.             demo++;
  550.             break;
  551.         case 'u':
  552.             usage();
  553.             exit(0);
  554.         case 'h':
  555.             height = atoi(optarg);
  556.             break;
  557.         case 'm':
  558.             mincolindex = atoi(optarg);
  559.             break;
  560.         case 'n':
  561.             nummaps = atoi(optarg);
  562.             break;
  563.         case 'o':
  564.             ++oflag;
  565.             outname = optarg;
  566.             break;
  567.         case 'r':
  568.             ranbeta++;
  569.             break;
  570.         case 's':
  571.             ++spin;
  572.             break;
  573.         case 'w':
  574.             width = atoi(optarg);
  575.             break;
  576.         case 'F':
  577.             full++;
  578.             break;
  579.         case 'D':
  580.             delay = atoi(optarg);
  581.             break;
  582.         case 'H':
  583.             beta = atof(optarg);
  584.             break;
  585.         case 'R':
  586.             useroot++;
  587.             break;
  588.         case 'S':
  589.             sea_level = atof(optarg);
  590.             break;
  591.         case 'T':
  592.             nrows = 512;
  593.             break;
  594.         case 'V':
  595.             nrows = 256;
  596.             vflag++;
  597.             break;
  598.         case 'X':    xpos=atoi(optarg); break;
  599.         case 'Y':    ypos=atoi(optarg); break;
  600.         case '?':
  601.             usage();
  602.             exit(1);
  603.             break;
  604.         }
  605.     }
  606. }
  607.  
  608. void
  609. event_loop()
  610. {
  611.     int n;
  612.     XEvent event;
  613.  
  614.     n = XEventsQueued(dpy, QueuedAfterFlush);
  615.     while (n--) {
  616.         XNextEvent(dpy, &event);
  617.         switch(event.type) {
  618.             case KeyPress:
  619.                 Getkey(&event);
  620.                 break;
  621.             case Expose:
  622.                 redisplay(&event);
  623.                 break;
  624.             case ConfigureNotify:
  625.                 resize();
  626.                 break;
  627.         }
  628.     }
  629. }
  630.  
  631. void
  632. midpoint (w, N, H)
  633. double *w[];
  634. int N;
  635. double H;
  636. {
  637.     int i, j, d, D, col, startcol;
  638.     double std, ratio;
  639.  
  640.     D = N/2; d = D/2;
  641.     ratio = 1.0/pow(2.0,H); std = ratio;
  642.     while (D > 1) {
  643.         /* use diagonal neighborhood */
  644.         for (i=d; i<N; i += D)
  645.             for (j=d; j<N; j += D) {
  646.                 w[i][j]=((w[i+d][j+d]+w[i-d][j-d]+w[i+d][j-d]+w[i-d][j+d])
  647.                         *0.25) + (std*gauss());
  648.                 if (min > w[i][j]) min = w[i][j];
  649.                 if (max < w[i][j]) max = w[i][j];
  650.             }
  651.         event_loop();
  652.         /* use neighbors to N,E,W,S */
  653.         for (i=d; i<N; i += D) {
  654.             w[i][0]=((w[i-d][0]+w[i+d][0]+w[i][d])/3.0)+std*gauss();
  655.             if (min > w[i][0]) min = w[i][0];
  656.             if (max < w[i][0]) max = w[i][0];
  657.             w[i][N]=((w[i-d][N]+w[i+d][N]+w[i][N-d])/3.0) + std*gauss();
  658.             if (min > w[i][N]) min = w[i][N];
  659.             if (max < w[i][N]) max = w[i][N];
  660.             w[0][i]=((w[0][i-d]+w[0][i+d]+w[d][i])/3.0)+std*gauss();
  661.             if (min > w[0][i]) min = w[0][i];
  662.             if (max < w[0][i]) max = w[0][i];
  663.             w[N][i]=((w[N][i-d]+w[N][i+d]+w[N-d][i])/3.0) + std*gauss();
  664.             if (min > w[N][i]) min = w[N][i];
  665.             if (max < w[N][i]) max = w[N][i];
  666.         }
  667.         event_loop();
  668.         col = 0;
  669.         for (i=d; i<N; i += d) {    /* Fill the interior */
  670.             if (col%2)
  671.                 startcol = d;
  672.             else
  673.                 startcol = D;
  674.             for (j=startcol; j<N; j += D) {
  675.                 w[i][j] = ((w[i][j+d]+w[i][j-d]+w[i+d][j]+w[i-d][j])*0.25)
  676.                             +std*gauss();
  677.                 if (min > w[i][j]) min = w[i][j];
  678.                 if (max < w[i][j]) max = w[i][j];
  679.             }
  680.             col++;
  681.         }
  682.         D /= 2; d = D/2; std *= ratio;
  683.         event_loop();
  684.     }
  685. }
  686.  
  687. main(argc,argv)
  688. int argc;
  689. char *argv[];
  690. {
  691.     static int i, j, k;
  692.     XSizeHints hint;
  693.     Atom __SWM_VROOT = None;
  694.     Window rootReturn, parentReturn, *children;
  695.     unsigned int numChildren;
  696.     extern void srand48(), init_color();
  697.     
  698.     parseargs(argc,argv);
  699.     dpy = XOpenDisplay("");
  700.     screen = DefaultScreen(dpy);
  701.     if (full || useroot) {
  702.         width = XDisplayWidth(dpy, screen);
  703.         height = XDisplayHeight(dpy, screen);
  704.         while (nrows < Max(width, height))
  705.             nrows *= 2;
  706.     }
  707.     if (width > nrows)
  708.         width = nrows;
  709.     if (height > nrows)
  710.         height = nrows;
  711.     first_row = (nrows - height) / 2;
  712.     last_row = nrows - first_row;
  713.     offset = (nrows - width) / 2;
  714.     maxcolor  = (int)XDisplayCells(dpy, screen);
  715.     if (maxcolor <= 16) {
  716.         STARTCOLOR = 2; delay = 100;
  717.         INDEXINC = 1; mincolindex = 5;
  718.     }
  719.     colors = maxcolor - STARTCOLOR;
  720.     maxcolor = Min(maxcolor, MAXCOLOR);
  721.     origin[0] = origin[1] = 0;
  722.     /*
  723.     * Create the pixmap to hold the fractal topographic map
  724.     */
  725.     pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy), width, height, 
  726.                            DefaultDepth(dpy, screen));
  727.     /*
  728.     * Create the window to display the fractal topographic map
  729.     */
  730.     if (xpos == -1)
  731.         hint.x = (XDisplayWidth(dpy, screen) - width)/2;
  732.     else
  733.         hint.x = xpos;
  734.     if (ypos == -1)
  735.         hint.y = (XDisplayHeight(dpy, screen) - height)/2;
  736.     else
  737.         hint.y = ypos;
  738.     hint.width = width;
  739.     hint.height = height;
  740.     hint.flags = PPosition | PSize;
  741.     if (useroot) {
  742.         canvas = DefaultRootWindow(dpy);
  743.         /* search for virtual root (from ssetroot by Tom LaStrange) */
  744.         __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
  745.         XQueryTree(dpy,canvas,&rootReturn,&parentReturn,&children,&numChildren);
  746.         for (j = 0; j < numChildren; j++) {
  747.             Atom actual_type;
  748.             int actual_format;
  749.             long nitems, bytesafter;
  750.             Window *newRoot = NULL;
  751.  
  752.             if (XGetWindowProperty (dpy, children[j], __SWM_VROOT,0,1, False, 
  753.                 XA_WINDOW, &actual_type, &actual_format, &nitems, &bytesafter,
  754.                 (unsigned char **) &newRoot) == Success && newRoot) {
  755.                 canvas = *newRoot;
  756.                 break;
  757.             }
  758.         }
  759.     }
  760.     else {
  761.         canvas = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
  762.             hint.x, hint.y, width, height, 5, 0, 1);
  763.         XSetStandardProperties(dpy, canvas, "Xtopo by Ron Record",
  764.             "Xtopo", None, argv, argc, &hint);
  765.         XSelectInput(dpy,canvas,KeyPressMask|ExposureMask);
  766.         XMapRaised(dpy, canvas);
  767.         if (xpos == -1)
  768.             center_horizontal(dpy, canvas, width);
  769.         if (ypos == -1)
  770.             center_vertical(dpy, canvas, height);
  771.     }
  772.     XChangeProperty(dpy, canvas, XA_WM_CLASS, XA_STRING, 8, PropModeReplace, 
  773.                     "xtopo", strlen("xtopo"));
  774.     /*
  775.     * Create the window used to display the help info
  776.     */
  777.     hint.x = XDisplayWidth(dpy, screen) / 4;
  778.     hint.y = XDisplayHeight(dpy, screen) / 4;
  779.     hint.width = hint.x * 2;
  780.     hint.height = hint.y * 2;
  781.     help = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
  782.             hint.x, hint.y, hint.width, hint.height, 5, 0, 1);
  783.     XSetWindowBackground(dpy, help, BlackPixel(dpy, screen));
  784.     /* Title */
  785.     XSetStandardProperties(dpy, help, "Help", "Help", None, argv, argc, &hint);
  786.     XSelectInput(dpy,help,KeyPressMask|ExposureMask);
  787.     /* Try to write into a new color map */
  788.     cmap = XCreateColormap(dpy, canvas, DefaultVisual(dpy, screen), AllocAll);
  789.     init_color(dpy, canvas, cmap, Colors, STARTCOLOR, mincolindex, maxcolor,
  790.                 numwheels,"xtopo", "Xtopo", 0);
  791.     /* install new color map */
  792.     if (!useroot) {
  793.         XSetWindowColormap(dpy, canvas, cmap);
  794.         XSetWindowColormap(dpy, help, cmap);
  795.     }
  796.     init_contexts();
  797.     setupmem();
  798.     Clear();
  799.     srand48((long)time(0));
  800.     for (k=0; k!=nummaps; k++) {
  801.         if (ranbeta)
  802.             beta = (drand48() * (rmax - rmin)) + rmin;
  803.         next = 0; min = max = 0.0;
  804.         origin[0] = origin[1] = 0;
  805.         InitBuffer(&Points, maxcolor);
  806.         init_pts(xy,nrows);
  807.         midpoint(xy,nrows,beta);
  808.         if (!useroot)
  809.             XSelectInput(dpy,canvas,KeyPressMask|ExposureMask|
  810.                                     StructureNotifyMask);
  811.         for (j=first_row; j < last_row; j++) {
  812.             event_loop();
  813.             grafline(xy,offset,width,j);
  814.         }
  815.         FlushBuffer(dpy, canvas, pixmap, Data_GC, &Points, 0, maxcolor);
  816.         if (oflag)
  817.             save();
  818.         if (demo) {
  819.             event_loop();
  820.             DemoSpin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, 4);
  821.             event_loop();
  822.             for (i=0; i<=MAXWHEELS; i++) {
  823.                 init_color(dpy, canvas, cmap, Colors, STARTCOLOR, mincolindex, 
  824.                         maxcolor, i, "xtopo", "Xtopo", 0);
  825.                 sleep(1);
  826.                 event_loop();
  827.             }
  828.         }
  829.         else if (useroot) {
  830.             XSetWindowBackgroundPixmap(dpy, canvas, pixmap);
  831.             XFreePixmap(dpy, pixmap);
  832.             XClearWindow(dpy, canvas);
  833.             XFlush(dpy);
  834.             XCloseDisplay(dpy);
  835.         }
  836.         else {
  837.             XSync(dpy, True);
  838.             if (spin)
  839.                 Spin(dpy, cmap, Colors, STARTCOLOR, maxcolor, delay, 0);
  840.             for (;;) {
  841.                 event_loop();
  842.                 if (next) break;
  843.             }
  844.         }
  845.     }
  846.     Cleanup();
  847.     exit(0);
  848. }
  849.